<template>
  <div id="app">
    <div class="sidebar">
      <div class="heading">
        <h1>Our locations</h1>
      </div>
      <div id="listings" class="listings"></div>
    </div>
    <div id="map" class="map"></div>
  </div>
</template>

<script>
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';

const stores = {
  type: 'FeatureCollection',
  features: [
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.034084142948, 38.909671288923],
      },
      properties: {
        phoneFormatted: '(202) 234-7336',
        phone: '2022347336',
        address: '1471 P St NW',
        city: 'Washington DC',
        country: 'United States',
        crossStreet: 'at 15th St NW',
        postalCode: '20005',
        state: 'D.C.',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.049766, 38.900772],
      },
      properties: {
        phoneFormatted: '(202) 507-8357',
        phone: '2025078357',
        address: '2221 I St NW',
        city: 'Washington DC',
        country: 'United States',
        crossStreet: 'at 22nd St NW',
        postalCode: '20037',
        state: 'D.C.',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.043929, 38.910525],
      },
      properties: {
        phoneFormatted: '(202) 387-9338',
        phone: '2023879338',
        address: '1512 Connecticut Ave NW',
        city: 'Washington DC',
        country: 'United States',
        crossStreet: 'at Dupont Circle',
        postalCode: '20036',
        state: 'D.C.',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.0672, 38.90516896],
      },
      properties: {
        phoneFormatted: '(202) 337-9338',
        phone: '2023379338',
        address: '3333 M St NW',
        city: 'Washington DC',
        country: 'United States',
        crossStreet: 'at 34th St NW',
        postalCode: '20007',
        state: 'D.C.',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.002583742142, 38.887041080933],
      },
      properties: {
        phoneFormatted: '(202) 547-9338',
        phone: '2025479338',
        address: '221 Pennsylvania Ave SE',
        city: 'Washington DC',
        country: 'United States',
        crossStreet: 'btwn 2nd & 3rd Sts. SE',
        postalCode: '20003',
        state: 'D.C.',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-76.933492720127, 38.99225245786],
      },
      properties: {
        address: '8204 Baltimore Ave',
        city: 'College Park',
        country: 'United States',
        postalCode: '20740',
        state: 'MD',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.097083330154, 38.980979],
      },
      properties: {
        phoneFormatted: '(301) 654-7336',
        phone: '3016547336',
        address: '4831 Bethesda Ave',
        cc: 'US',
        city: 'Bethesda',
        country: 'United States',
        postalCode: '20814',
        state: 'MD',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.359425054188, 38.958058116661],
      },
      properties: {
        phoneFormatted: '(571) 203-0082',
        phone: '5712030082',
        address: '11935 Democracy Dr',
        city: 'Reston',
        country: 'United States',
        crossStreet: 'btw Explorer & Library',
        postalCode: '20190',
        state: 'VA',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.10853099823, 38.880100922392],
      },
      properties: {
        phoneFormatted: '(703) 522-2016',
        phone: '7035222016',
        address: '4075 Wilson Blvd',
        city: 'Arlington',
        country: 'United States',
        crossStreet: 'at N Randolph St.',
        postalCode: '22203',
        state: 'VA',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-75.28784, 40.008008],
      },
      properties: {
        phoneFormatted: '(610) 642-9400',
        phone: '6106429400',
        address: '68 Coulter Ave',
        city: 'Ardmore',
        country: 'United States',
        postalCode: '19003',
        state: 'PA',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-75.20121216774, 39.954030175164],
      },
      properties: {
        phoneFormatted: '(215) 386-1365',
        phone: '2153861365',
        address: '3925 Walnut St',
        city: 'Philadelphia',
        country: 'United States',
        postalCode: '19104',
        state: 'PA',
      },
    },
    {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [-77.043959498405, 38.903883387232],
      },
      properties: {
        phoneFormatted: '(202) 331-3355',
        phone: '2023313355',
        address: '1901 L St. NW',
        city: 'Washington DC',
        country: 'United States',
        crossStreet: 'at 19th St',
        postalCode: '20036',
        state: 'D.C.',
      },
    },
  ],
};
export default {
  data() {
    return {
      // map 地图对象实例
      map: null,
      stores: Object.freeze({}),
    };
  },
  beforeCreate() {
    // 兼容旧版本没有remove()的情况
    if (!('remove' in Element.prototype)) {
      Element.prototype.remove = function () {
        if (this.parentNode) {
          this.parentNode.removeChild(this);
        }
      };
    }
  },
  mounted() {
    this._createBaseMap();
  },
  methods: {
    _createBaseMap() {
      mapboxgl.accessToken =
        'pk.eyJ1IjoiaW54bG54IiwiYSI6ImNsMzRmZDE4dTBhOWczaWs3a2psanphMnUifQ.iKIlYhNlW_13OqBJLOc9sw';

      const map = new mapboxgl.Map({
        container: 'map',
        //自己绘制的样式地图令牌
        antialias: true, //抗锯齿
        style: 'mapbox://styles/mapbox/dark-v10',
        // center: [113.97923191113188, 22.589860256941634],
        center: [-77.034084, 38.909671],
        zoom: 12,
      });

      this.map = map;
      window.map = map;
      const that = this;

      map.on('load', function () {
        map.addSource('places', {
          type: 'geojson',
          data: stores,
        });
        // 向地图中添加数据图层
        map.addLayer({
          id: 'locations',
          type: 'symbol',
          // 添加包含有坐标和附加信息的GeoJSON数据源
          source: {
            type: 'geojson',
            data: stores,
          },
          layout: {
            'icon-image': 'restaurant-15',
            'icon-allow-overlap': true,
          },
        });

        stores.features.forEach(function (marker, index) {
          // 给标签创建一个div
          var el = document.createElement('div');
          el.dataset.index = index;
          // Add a class called 'marker' to each div
          el.className = 'marker';
          // 图片默认为中心显示。您可以调整显示的中心。
          // 创建自定义标签，调整中心位置，然后添加到地图中
          new mapboxgl.Marker(el, { offset: [0, -23] })
            .setLngLat(marker.geometry.coordinates)
            .addTo(map);
          el.addEventListener('click', function (e) {
            var activeItem = document.getElementsByClassName('active');
            // 1. 地图重定位
            that.flyToStore(marker);
            // 2. 关闭其他所有的弹出窗口并显示新的弹出窗口
            that.createPopUp(marker);
            // 3. 移除所有的高亮显示并高亮显示新的链接
            e.stopPropagation();
            if (activeItem[0]) {
              activeItem[0].classList.remove('active');
            }
            console.log('e :>> ', e);
            var listing = document.getElementById(
              'listing-' + e.target.dataset.index
            );
            console.log(listing);
            listing.classList.add('active');
          });
        });
      });
      this.buildLocationList(stores);

      // 对地图位置点击事件的响应
      map.on('click', function (e) {
        // 查询在视窗中所有的位置
        var features = map.queryRenderedFeatures(e.point, {
          layers: ['locations'],
        });
        console.log('features :>> ', features.length);
        if (features.length) {
          var clickedPoint = features[0];
          // 1. 地图重定位
          that.flyToStore(clickedPoint);
          // 2. 关闭其他所有的弹出窗口并显示新的弹出窗口
          that.createPopUp(clickedPoint);
          // 3. 移除所有的高亮显示并高亮显示新的链接
          var activeItem = document.getElementsByClassName('active');
          if (activeItem[0]) {
            activeItem[0].classList.remove('active');
          }
          // 查找store.features与接受点击事件的clickedPoint所关联的索引号
          var selectedFeature = clickedPoint.properties.address;
          var selectedFeatureIndex = 0;
          for (var i = 0; i < stores.features.length; i++) {
            if (stores.features[i].properties.address === selectedFeature) {
              selectedFeatureIndex = i;
            }
          }
          // 选择被选中的商店并添加到active类中
          var listing = document.getElementById(
            'listing-' + selectedFeatureIndex
          );
          listing.classList.add('active');
        }
      });

      // zoom变化时打印zoom值
      map.on('zoom', function (e) {
        console.log('zoom:', e.target.getZoom());
      });
    },
    // 这个函数自动遍历所有的 Sweetgreen 位置，并且添加它们到侧边栏中
    buildLocationList(data) {
      const that = this;
      // 遍历所有的商店
      for (let i = 0; i < data.features.length; i++) {
        var currentFeature = data.features[i];
        // 重新命名data.feature.properties为`prop`
        // 以避免过长字符串的反复出现
        var prop = currentFeature.properties;
        // 选择列表容器的HTML元素
        // 为每一个商店添加一个item类的div
        var listings = document.getElementById('listings');
        var listing = listings.appendChild(document.createElement('div'));
        listing.className = 'item';
        listing.id = 'listing-' + i;

        // 为每一个商店添加一个title类的链接
        // 并将其与位置相互关联
        var link = listing.appendChild(document.createElement('a'));
        link.href = '#';
        link.className = 'title';
        link.dataPosition = i;
        link.innerHTML = prop.address;

        // 对链接点击的响应
        link.addEventListener('click', function () {
          // 更新currentFeature至被点击的链接
          var clickedListing = data.features[this.dataPosition];
          // 1. 地图重定位
          that.flyToStore(clickedListing);
          // 2. 关闭其他所有的弹出窗口并显示新的弹出窗口
          that.createPopUp(clickedListing);
          // 3. 移除所有的高亮显示并高亮显示新的链接
          var activeItem = document.getElementsByClassName('active');
          if (activeItem[0]) {
            activeItem[0].classList.remove('active');
          }
          this.parentNode.classList.add('active');
        });

        // 为每一个商店创建一个details类的div
        // 并添加相应的城市和电话号码
        var details = listing.appendChild(document.createElement('div'));
        details.innerHTML = prop.city;
        if (prop.phone) {
          details.innerHTML += ' · ' + prop.phoneFormatted;
        }
      }
    },
    // 飞向指定的经纬度
    flyToStore(currentFeature) {
      this.map.flyTo({
        center: currentFeature.geometry.coordinates,
        zoom: 15,
      });
    },
    // 创建了一个弹出层
    createPopUp(currentFeature) {
      const popUps = document.getElementsByClassName('mapboxgl-popup');
      // 我们需要检查并移除已经存在的弹出窗口
      if (popUps[0]) popUps[0].remove();

      new mapboxgl.Popup({ closeOnClick: false })
        .setLngLat(currentFeature.geometry.coordinates)
        .setHTML(
          '<h3>Sweetgreen</h3>' +
            '<h4>' +
            currentFeature.properties.address +
            '</h4>'
        )
        .addTo(this.map);
    },
  },
  beforeDestroy() {
    // this.map.remove();
    // this.map = null;
  },
};
</script>

<style>
body {
  background: #fff;
  color: #8a8a8a;
  font: 500 20px/26px 'Helvetica Neue', Helvetica, Arial, Sans-serif;
  margin: 0;
  padding: 0;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

h1 {
  font-size: 22px;
  margin: 0;
  font-weight: 400;
  line-height: 20px;
  padding: 20px 2px;
}

a {
  color: #404040;
  text-decoration: none;
}

a:hover {
  color: #101010;
}

/*这个页面被分为了地图和侧边栏。侧边栏相对宽度为页面的三分之一，地图容器为三分之二。您可以自行调整相对宽度。*/
.sidebar {
  position: absolute;
  width: 20%;
  height: 100%;
  top: 0;
  left: 0;
  overflow: hidden;
  border-right: 1px solid rgba(0, 0, 0, 0.25);
}

.pad2 {
  padding: 20px;
}

.map {
  position: absolute;
  left: 20%;
  width: 80%;
  top: 0;
  bottom: 0;
}

.heading {
  background: #fff;
  border-bottom: 1px solid #eee;
  height: 60px;
  line-height: 60px;
  padding: 0 10px;
}

.listings {
  height: 100%;
  overflow: auto;
  padding-bottom: 60px;
}

.listings .item {
  display: block;
  border-bottom: 1px solid #eee;
  padding: 10px;
  text-decoration: none;
}

.listings .item:last-child {
  border-bottom: none;
}

.listings .item .title {
  display: block;
  color: #00853e;
  font-weight: 700;
}

.listings .item .title small {
  font-weight: 400;
}

.listings .item.active .title,
.listings .item .title:hover {
  color: #8cc63f;
}

.listings .item.active {
  background-color: #f8f8f8;
}

::-webkit-scrollbar {
  width: 3px;
  height: 3px;
  border-left: 0;
  background: rgba(0, 0, 0, 0.1);
}

::-webkit-scrollbar-track {
  background: none;
}

::-webkit-scrollbar-thumb {
  background: #00853e;
  border-radius: 0;
}

.clearfix {
  display: block;
}

.clearfix::after {
  content: '.';
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

/* 弹出层样式 */

/* Marker tweaks */

.mapboxgl-popup {
  padding-bottom: 50px;
}

.mapboxgl-popup-close-button {
  display: none;
}

.mapboxgl-popup-content {
  font: 400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif;
  padding: 0;
  width: 180px;
}

.mapboxgl-popup-content-wrapper {
  padding: 1%;
}

.mapboxgl-popup-content h3 {
  background: #91c949;
  color: #fff;
  margin: 0;
  display: block;
  padding: 10px;
  border-radius: 3px 3px 0 0;
  font-weight: 700;
  margin-top: -15px;
}

.mapboxgl-popup-content h4 {
  margin: 0;
  display: block;
  padding: 10px;
  font-weight: 400;
}

.mapboxgl-popup-content div {
  padding: 10px;
}

.mapboxgl-container .leaflet-marker-icon {
  cursor: pointer;
}

.mapboxgl-popup-anchor-top > .mapboxgl-popup-content {
  margin-top: 15px;
}

.mapboxgl-popup-anchor-top > .mapboxgl-popup-tip {
  border-bottom-color: #91c949;
}

/* marker图标的样式设置 */
.marker {
  border: none;
  cursor: pointer;
  height: 56px;
  width: 56px;
  background-image: url('../assets/marker.png');
  background-color: rgba(0, 0, 0, 0);
}
</style>
